home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 June / CHIP Haziran 2001.iso / prog / haziran / 19 / setup.exe / data.z / p9030_lib.c < prev    next >
C/C++ Source or Header  |  2001-04-11  |  26KB  |  882 lines

  1. ////////////////////////////////////////////////////////////////
  2. // File - P9030_LIB.C
  3. //
  4. // Library for 'WinDriver for PLX 9030' API. 
  5. // The basic idea is to get a handle for the board
  6. // with P9030_Open() and use it in the rest of the program
  7. // when calling WD functions.  Call P9030_Close() when done.
  8. // 
  9. ////////////////////////////////////////////////////////////////
  10.  
  11. #include "p9030_lib.h"
  12. #include "../../../include/windrvr_int_thread.h"
  13. #include <stdio.h>
  14.  
  15. // this string is set to an error message, if one occurs
  16. CHAR P9030_ErrorString[1024];
  17.  
  18. // internal data structures
  19. typedef struct
  20. {
  21.     WD_INTERRUPT Int;
  22.     HANDLE hThread;
  23.     WD_TRANSFER Trans[2];
  24.     P9030_INT_HANDLER funcIntHandler;
  25. } P9030_INTERRUPT;
  26.  
  27. typedef struct
  28. {
  29.     DWORD dwLocalBase;
  30.     DWORD dwMask;
  31.     DWORD dwBytes;
  32.     DWORD dwAddr;
  33.     DWORD dwAddrDirect;
  34.     BOOL  fIsMemory;
  35. } P9030_ADDR_DESC;
  36.  
  37. typedef struct P9030_STRUCT
  38. {
  39.     HANDLE hWD;
  40.     WD_CARD cardLock;
  41.     WD_PCI_SLOT pciSlot;
  42.     WD_CARD_REGISTER cardReg;
  43.     P9030_ADDR_DESC addrDesc[AD_PCI_BARS];
  44.     BOOL   fUseInt;
  45.     P9030_INTERRUPT Int;
  46. } P9030_STRUCT;
  47.  
  48. // internal function used by P9030_Open()
  49. BOOL P9030_DetectCardElements(P9030_HANDLE hPlx);
  50. // internal function used by P9030_Read... and P9030_Write... functions
  51. void P9030_SetMode (P9030_HANDLE hPlx, P9030_ADDR addrSpace, P9030_MODE mode, DWORD dwLocalAddr);
  52.  
  53. DWORD P9030_CountCards (DWORD dwVendorID, DWORD dwDeviceID)
  54. {
  55.     WD_VERSION ver;
  56.     WD_PCI_SCAN_CARDS pciScan;
  57.     HANDLE hWD = INVALID_HANDLE_VALUE;
  58.  
  59.     P9030_ErrorString[0] = '\0';
  60.     hWD = WD_Open();
  61.     // check if handle valid & version OK
  62.     if (hWD==INVALID_HANDLE_VALUE) 
  63.     {
  64.         sprintf( P9030_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  65.         return 0;
  66.     }
  67.  
  68.     BZERO(ver);
  69.     WD_Version(hWD,&ver);
  70.     if (ver.dwVer<WD_VER) 
  71.     {
  72.         sprintf( P9030_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  73.         WD_Close (hWD);
  74.         return 0;
  75.     }
  76.  
  77.     BZERO(pciScan);
  78.     pciScan.searchId.dwVendorId = dwVendorID;
  79.     pciScan.searchId.dwDeviceId = dwDeviceID;
  80.     WD_PciScanCards (hWD, &pciScan);
  81.     WD_Close (hWD);
  82.     if (pciScan.dwCards==0)
  83.         sprintf( P9030_ErrorString, "no cards found\n");
  84.     return pciScan.dwCards;
  85. }
  86.  
  87.  
  88. BOOL P9030_Open (P9030_HANDLE *phPlx, DWORD dwVendorID, DWORD dwDeviceID, DWORD nCardNum, DWORD options)
  89. {
  90.     P9030_HANDLE hPlx = (P9030_HANDLE) malloc (sizeof (P9030_STRUCT));
  91.  
  92.     WD_VERSION ver;
  93.     WD_PCI_SCAN_CARDS pciScan;
  94.     WD_PCI_CARD_INFO pciCardInfo;
  95.  
  96.     *phPlx = NULL;
  97.     P9030_ErrorString[0] = '\0';
  98.     BZERO(*hPlx);
  99.  
  100.     hPlx->cardReg.hCard = 0;
  101.     hPlx->hWD = WD_Open();
  102.  
  103.     // check if handle valid & version OK
  104.     if (hPlx->hWD==INVALID_HANDLE_VALUE) 
  105.     {
  106.         sprintf( P9030_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  107.         goto Exit;
  108.     }
  109.  
  110.     BZERO(ver);
  111.     WD_Version(hPlx->hWD,&ver);
  112.     if (ver.dwVer<WD_VER) 
  113.     {
  114.         sprintf( P9030_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  115.         goto Exit;
  116.     }
  117.  
  118.     BZERO(pciScan);
  119.     pciScan.searchId.dwVendorId = dwVendorID;
  120.     pciScan.searchId.dwDeviceId = dwDeviceID;
  121.     WD_PciScanCards (hPlx->hWD, &pciScan);
  122.     if (pciScan.dwCards==0) // Found at least one card
  123.     {
  124.         sprintf( P9030_ErrorString, "Could not find PCI card\n");
  125.         goto Exit;
  126.     }
  127.     if (pciScan.dwCards<=nCardNum)
  128.     {
  129.         sprintf( P9030_ErrorString, "Card out of range of available cards\n");
  130.         goto Exit;
  131.     }
  132.  
  133.     BZERO(pciCardInfo);
  134.     pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum];
  135.     hPlx->pciSlot = pciCardInfo.pciSlot;
  136.  
  137.     WD_PciGetCardInfo (hPlx->hWD, &pciCardInfo);
  138.     hPlx->cardReg.Card = pciCardInfo.Card;
  139.  
  140.     hPlx->fUseInt = (options & P9030_OPEN_USE_INT) ? TRUE : FALSE;
  141.     if (!hPlx->fUseInt)
  142.     {
  143.         DWORD i;
  144.         // Remove interrupt item if not needed
  145.         for (i=0; i<hPlx->cardReg.Card.dwItems; i++)
  146.         {
  147.             WD_ITEMS *pItem = &hPlx->cardReg.Card.Item[i];
  148.             if (pItem->item==ITEM_INTERRUPT)
  149.                 pItem->item = ITEM_NONE;
  150.         }
  151.     }
  152.     else
  153.     {
  154.         DWORD i;
  155.         // make interrupt resource sharable
  156.         for (i=0; i<hPlx->cardReg.Card.dwItems; i++)
  157.         {
  158.             WD_ITEMS *pItem = &hPlx->cardReg.Card.Item[i];
  159.             if (pItem->item==ITEM_INTERRUPT)
  160.                 pItem->fNotSharable = FALSE;
  161.         }
  162.     }
  163.  
  164.     hPlx->cardReg.fCheckLockOnly = FALSE;
  165.     WD_CardRegister (hPlx->hWD, &hPlx->cardReg);
  166.     if (hPlx->cardReg.hCard==0)
  167.     {
  168.         sprintf ( P9030_ErrorString, "Failed locking device\n");
  169.         goto Exit;
  170.     }
  171.  
  172.     if (!P9030_DetectCardElements(hPlx))
  173.     {
  174.         sprintf ( P9030_ErrorString, "Card does not have all items expected for PLX 9030\n");
  175.         goto Exit;
  176.     }
  177.  
  178.     // Open finished OK
  179.     *phPlx = hPlx;
  180.     return TRUE;
  181.  
  182. Exit:
  183.     // Error durin Open
  184.     if (hPlx->cardReg.hCard) 
  185.         WD_CardUnregister(hPlx->hWD, &hPlx->cardReg);
  186.     if (hPlx->hWD!=INVALID_HANDLE_VALUE)
  187.         WD_Close(hPlx->hWD);
  188.     free (hPlx);
  189.     return FALSE;
  190. }
  191.  
  192. void P9030_GetPciSlot(P9030_HANDLE hPlx, WD_PCI_SLOT *pPciSlot)
  193. {
  194.     *pPciSlot = hPlx->pciSlot;
  195. }
  196.  
  197. DWORD P9030_ReadPCIReg(P9030_HANDLE hPlx, DWORD dwReg)
  198. {
  199.     WD_PCI_CONFIG_DUMP pciCnf;
  200.     DWORD dwVal;
  201.  
  202.     BZERO (pciCnf);
  203.     pciCnf.pciSlot = hPlx->pciSlot;
  204.     pciCnf.pBuffer = &dwVal;
  205.     pciCnf.dwOffset = dwReg;
  206.     pciCnf.dwBytes = 4;
  207.     pciCnf.fIsRead = TRUE;
  208.     WD_PciConfigDump(hPlx->hWD,&pciCnf);
  209.     return dwVal;
  210. }
  211.  
  212. void P9030_WritePCIReg(P9030_HANDLE hPlx, DWORD dwReg, DWORD dwData)
  213. {
  214.     WD_PCI_CONFIG_DUMP pciCnf;
  215.  
  216.     BZERO (pciCnf);
  217.     pciCnf.pciSlot = hPlx->pciSlot;
  218.     pciCnf.pBuffer = &dwData;
  219.     pciCnf.dwOffset = dwReg;
  220.     pciCnf.dwBytes = 4;
  221.     pciCnf.fIsRead = FALSE;
  222.     WD_PciConfigDump(hPlx->hWD,&pciCnf);
  223. }
  224.  
  225. BOOL P9030_DetectCardElements(P9030_HANDLE hPlx)
  226. {
  227.     DWORD i;
  228.     DWORD ad_sp;
  229.  
  230.     BZERO(hPlx->Int);
  231.     BZERO(hPlx->addrDesc);
  232.  
  233.     for (i=0; i<hPlx->cardReg.Card.dwItems; i++)
  234.     {
  235.         WD_ITEMS *pItem = &hPlx->cardReg.Card.Item[i];
  236.  
  237.         switch (pItem->item)
  238.         {
  239.         case ITEM_MEMORY:
  240.         case ITEM_IO:
  241.             {
  242.                 DWORD dwBytes;
  243.                 DWORD dwAddr;
  244.                 DWORD dwAddrDirect = 0;
  245.                 DWORD dwPhysAddr;
  246.                 BOOL fIsMemory;
  247.                 if (pItem->item==ITEM_MEMORY)
  248.                 {
  249.                     dwBytes = pItem->I.Mem.dwBytes;
  250.                     dwAddr = pItem->I.Mem.dwTransAddr;
  251.                     dwAddrDirect = pItem->I.Mem.dwUserDirectAddr;
  252.                     dwPhysAddr = pItem->I.Mem.dwPhysicalAddr;
  253.                     fIsMemory = TRUE;
  254.                 }
  255.                 else 
  256.                 {
  257.                     dwBytes = pItem->I.IO.dwBytes;
  258.                     dwAddr = pItem->I.IO.dwAddr;
  259.                     dwPhysAddr = dwAddr & 0xffff;
  260.                     fIsMemory = FALSE;
  261.                 }
  262.  
  263.                 for (ad_sp=P9030_ADDR_REG; ad_sp<=P9030_ADDR_EPROM; ad_sp++)
  264.                 {
  265.                     DWORD dwPCIAddr;
  266.                     DWORD dwPCIReg;
  267.  
  268.                     if (hPlx->addrDesc[ad_sp].dwAddr) continue;
  269.                     if (ad_sp==P9030_ADDR_REG) dwPCIReg = PCI_BAR0;
  270.                     else if (ad_sp<P9030_ADDR_EPROM) 
  271.                         dwPCIReg = PCI_BAR2 + 4*(ad_sp-P9030_ADDR_SPACE0);
  272.                     else dwPCIReg = PCI_ERBAR;
  273.                     dwPCIAddr = P9030_ReadPCIReg(hPlx, dwPCIReg);
  274.                     if (dwPCIAddr & 1)
  275.                     {
  276.                         if (fIsMemory) continue;
  277.                         dwPCIAddr &= ~0x3;
  278.                     }
  279.                     else
  280.                     {
  281.                         if (!fIsMemory) continue;
  282.                         dwPCIAddr &= ~0xf;
  283.                     }
  284.                     if (dwPCIAddr==dwPhysAddr)
  285.                         break;
  286.                 }
  287.                 if (ad_sp<=P9030_ADDR_EPROM)
  288.                 {
  289.                     DWORD j;
  290.                     hPlx->addrDesc[ad_sp].dwBytes = dwBytes;
  291.                     hPlx->addrDesc[ad_sp].dwAddr = dwAddr;
  292.                     hPlx->addrDesc[ad_sp].dwAddrDirect = dwAddrDirect;
  293.                     hPlx->addrDesc[ad_sp].fIsMemory = fIsMemory;
  294.                     hPlx->addrDesc[ad_sp].dwMask = 0;
  295.                     for (j=1; j<hPlx->addrDesc[ad_sp].dwBytes && j!=0x80000000; j *= 2)
  296.                     {
  297.                         hPlx->addrDesc[ad_sp].dwMask = 
  298.                             (hPlx->addrDesc[ad_sp].dwMask << 1) | 1;
  299.                     }
  300.                 }
  301.             }
  302.             break;
  303.         case ITEM_INTERRUPT:
  304.             if (hPlx->Int.Int.hInterrupt) return FALSE;
  305.             hPlx->Int.Int.hInterrupt = pItem->I.Int.hInterrupt;
  306.             break;
  307.         }
  308.     }
  309.  
  310.     // check that all the items needed were found
  311.     // check if interrupt found
  312.     if (hPlx->fUseInt && !hPlx->Int.Int.hInterrupt) 
  313.     {
  314.         return FALSE;
  315.     }
  316.  
  317.     // check that the registers space was found
  318.     if (!P9030_IsAddrSpaceActive(hPlx, P9030_ADDR_REG))
  319.             //|| hPlx->addrDesc[P9030_ADDR_REG].dwBytes!=P9030_RANGE_REG)
  320.         return FALSE;
  321.  
  322.     // check that at least one memory space was found
  323.     // for (i = P9030_ADDR_SPACE0; i<=P9030_ADDR_EPROM; i++)
  324.     //     if (P9030_IsAddrSpaceActive(hPlx, i)) break;
  325.     // if (i>P9030_ADDR_EPROM) return FALSE;
  326.  
  327.     return TRUE;
  328. }
  329.  
  330. void P9030_Close(P9030_HANDLE hPlx)
  331. {
  332.     // disable interrupts
  333.     if (P9030_IntIsEnabled(hPlx))
  334.         P9030_IntDisable(hPlx);
  335.  
  336.     // unregister card
  337.     if (hPlx->cardReg.hCard) 
  338.         WD_CardUnregister(hPlx->hWD, &hPlx->cardReg);
  339.  
  340.     // close WinDriver
  341.     WD_Close(hPlx->hWD);
  342.  
  343.     free (hPlx);
  344. }
  345.  
  346. BOOL P9030_IsAddrSpaceActive(P9030_HANDLE hPlx, P9030_ADDR addrSpace)
  347. {
  348.     return hPlx->addrDesc[addrSpace].dwAddr!=0;
  349. }
  350.  
  351. DWORD P9030_ReadReg (P9030_HANDLE hPlx, DWORD dwReg)
  352. {
  353.     return P9030_ReadSpaceDWord(hPlx, P9030_ADDR_REG, dwReg);
  354. }
  355.  
  356. void P9030_WriteReg (P9030_HANDLE hPlx, DWORD dwReg, DWORD dwData)
  357. {
  358.     P9030_WriteSpaceDWord(hPlx, P9030_ADDR_REG, dwReg, dwData);
  359. }
  360.  
  361. void P9030_SetMode (P9030_HANDLE hPlx, P9030_ADDR addrSpace, P9030_MODE mode, DWORD dwLocalAddr)
  362. {
  363.     DWORD dwRegOffset = 4*(addrSpace-P9030_ADDR_SPACE0);
  364.     P9030_ADDR_DESC *addrDesc = &hPlx->addrDesc[addrSpace];
  365.     addrDesc->dwLocalBase = dwLocalAddr & ~addrDesc->dwMask;
  366.     addrDesc->dwLocalBase |= BIT0;
  367.     P9030_WriteReg (hPlx, P9030_LAS0BA + dwRegOffset, addrDesc->dwLocalBase);
  368. }
  369.  
  370. BYTE P9030_ReadSpaceByte (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwOffset)
  371. {
  372.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  373.     {
  374.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  375.         BYTE *pByte = (BYTE *) dwAddr;
  376.         return *pByte;
  377.     }
  378.     else
  379.     {
  380.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  381.         WD_TRANSFER trans;
  382.         BZERO(trans);
  383.         trans.cmdTrans = RP_BYTE;
  384.         trans.dwPort = dwAddr;
  385.         WD_Transfer (hPlx->hWD, &trans);
  386.         return trans.Data.Byte;
  387.     }
  388. }
  389.  
  390. void P9030_WriteSpaceByte (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwOffset, BYTE data)
  391. {
  392.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  393.     {
  394.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  395.         BYTE *pByte = (BYTE *) dwAddr;
  396.         *pByte = data;
  397.     }
  398.     else
  399.     {
  400.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  401.         WD_TRANSFER trans;
  402.         BZERO(trans);
  403.         trans.cmdTrans = WP_BYTE;
  404.         trans.dwPort = dwAddr;
  405.         trans.Data.Byte = data;
  406.         WD_Transfer (hPlx->hWD, &trans);
  407.     }
  408. }
  409.  
  410. WORD P9030_ReadSpaceWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwOffset)
  411. {
  412.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  413.     {
  414.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  415.         WORD *pWord = (WORD *) dwAddr;
  416.         return *pWord;
  417.     }
  418.     else
  419.     {
  420.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  421.         WD_TRANSFER trans;
  422.         BZERO(trans);
  423.         trans.cmdTrans = RP_WORD;
  424.         trans.dwPort = dwAddr;
  425.         WD_Transfer (hPlx->hWD, &trans);
  426.         return trans.Data.Word;
  427.     }
  428. }
  429.  
  430. void P9030_WriteSpaceWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwOffset, WORD data)
  431. {
  432.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  433.     {
  434.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  435.         WORD *pWord = (WORD *) dwAddr;
  436.         *pWord = data;
  437.     }
  438.     else
  439.     {
  440.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  441.         WD_TRANSFER trans;
  442.         BZERO(trans);
  443.         trans.cmdTrans = WP_WORD;
  444.         trans.dwPort = dwAddr;
  445.         trans.Data.Word = data;
  446.         WD_Transfer (hPlx->hWD, &trans);
  447.     }
  448. }
  449.  
  450. DWORD P9030_ReadSpaceDWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwOffset)
  451. {
  452.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  453.     {
  454.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  455.         DWORD *pDword = (DWORD *) dwAddr;
  456.         return *pDword;
  457.     }
  458.     else
  459.     {
  460.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  461.         WD_TRANSFER trans;
  462.         BZERO(trans);
  463.         trans.cmdTrans = RP_DWORD;
  464.         trans.dwPort = dwAddr;
  465.         WD_Transfer (hPlx->hWD, &trans);
  466.         return trans.Data.Dword;
  467.     }
  468. }
  469.  
  470. void P9030_WriteSpaceDWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwOffset, DWORD data)
  471. {
  472.     if (hPlx->addrDesc[addrSpace].fIsMemory)
  473.     {
  474.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  475.         DWORD *pDword = (DWORD *) dwAddr;
  476.         *pDword = data;
  477.     }
  478.     else
  479.     {
  480.         DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  481.         WD_TRANSFER trans;
  482.         BZERO(trans);
  483.         trans.cmdTrans = WP_DWORD;
  484.         trans.dwPort = dwAddr;
  485.         trans.Data.Dword = data;
  486.         WD_Transfer (hPlx->hWD, &trans);
  487.     }
  488. }
  489.  
  490. void P9030_ReadWriteSpaceBlock (P9030_HANDLE hPlx, DWORD dwOffset, PVOID buf, 
  491.                     DWORD dwBytes, BOOL fIsRead, P9030_ADDR addrSpace, P9030_MODE mode)
  492. {
  493.     WD_TRANSFER trans;
  494.     DWORD dwAddr = hPlx->addrDesc[addrSpace].dwAddr + dwOffset;
  495.  
  496.     BZERO(trans);
  497.  
  498.     if (hPlx->addrDesc[addrSpace].fIsMemory) 
  499.     {
  500.         if (fIsRead) 
  501.         {
  502.             if (mode==P9030_MODE_BYTE) trans.cmdTrans = RM_SBYTE;
  503.             else if (mode==P9030_MODE_WORD) trans.cmdTrans = RM_SWORD;
  504.             else trans.cmdTrans = RM_SDWORD;
  505.         }
  506.         else 
  507.         {
  508.             if (mode==P9030_MODE_BYTE) trans.cmdTrans = WM_SBYTE;
  509.             else if (mode==P9030_MODE_WORD) trans.cmdTrans = WM_SWORD;
  510.             else trans.cmdTrans = WM_SDWORD;
  511.         }
  512.     }
  513.     else 
  514.     {
  515.         if (fIsRead) 
  516.         {
  517.             if (mode==P9030_MODE_BYTE) trans.cmdTrans = RP_SBYTE;
  518.             else if (mode==P9030_MODE_WORD) trans.cmdTrans = RP_SWORD;
  519.             else trans.cmdTrans = RP_SDWORD;
  520.         }
  521.         else 
  522.         {
  523.             if (mode==P9030_MODE_BYTE) trans.cmdTrans = WP_SBYTE;
  524.             else if (mode==P9030_MODE_WORD) trans.cmdTrans = WP_SWORD;
  525.             else trans.cmdTrans = WP_SDWORD;
  526.         }
  527.     }
  528.     trans.dwPort = dwAddr;
  529.     trans.fAutoinc = TRUE;
  530.     trans.dwBytes = dwBytes;
  531.     trans.dwOptions = 0;
  532.     trans.Data.pBuffer = buf;
  533.     WD_Transfer (hPlx->hWD, &trans);
  534. }
  535.  
  536. void P9030_ReadSpaceBlock (P9030_HANDLE hPlx, DWORD dwOffset, PVOID buf, 
  537.                     DWORD dwBytes, P9030_ADDR addrSpace, P9030_MODE mode)
  538. {
  539.     P9030_ReadWriteSpaceBlock (hPlx, dwOffset, buf, dwBytes, TRUE, addrSpace, mode);
  540. }
  541.  
  542. void P9030_WriteSpaceBlock (P9030_HANDLE hPlx, DWORD dwOffset, PVOID buf, 
  543.                      DWORD dwBytes, P9030_ADDR addrSpace, P9030_MODE mode)
  544. {
  545.     P9030_ReadWriteSpaceBlock (hPlx, dwOffset, buf, dwBytes, FALSE, addrSpace, mode);
  546. }
  547.  
  548. BYTE P9030_ReadByte (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwLocalAddr)
  549. {
  550.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  551.     P9030_SetMode (hPlx, addrSpace, P9030_MODE_BYTE, dwLocalAddr);
  552.     return P9030_ReadSpaceByte(hPlx, addrSpace, dwOffset);
  553. }
  554.  
  555. void P9030_WriteByte (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwLocalAddr, BYTE data)
  556. {
  557.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  558.     P9030_SetMode (hPlx, addrSpace, P9030_MODE_BYTE, dwLocalAddr);
  559.     P9030_WriteSpaceByte(hPlx, addrSpace, dwOffset, data);
  560. }
  561.  
  562. WORD P9030_ReadWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwLocalAddr)
  563. {
  564.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  565.     P9030_SetMode (hPlx, addrSpace, P9030_MODE_WORD, dwLocalAddr);
  566.     return P9030_ReadSpaceWord(hPlx, addrSpace, dwOffset);
  567. }
  568.  
  569. void P9030_WriteWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwLocalAddr, WORD data)
  570. {
  571.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  572.     P9030_SetMode (hPlx, addrSpace, P9030_MODE_WORD, dwLocalAddr);
  573.     P9030_WriteSpaceWord(hPlx, addrSpace, dwOffset, data);
  574. }
  575.  
  576. DWORD P9030_ReadDWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwLocalAddr)
  577. {
  578.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  579.     P9030_SetMode (hPlx, addrSpace, P9030_MODE_DWORD, dwLocalAddr);
  580.     return P9030_ReadSpaceDWord(hPlx, addrSpace, dwOffset);
  581. }
  582.  
  583. void P9030_WriteDWord (P9030_HANDLE hPlx, P9030_ADDR addrSpace, DWORD dwLocalAddr, DWORD data)
  584. {
  585.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  586.     P9030_SetMode (hPlx, addrSpace, P9030_MODE_DWORD, dwLocalAddr);
  587.     P9030_WriteSpaceDWord(hPlx, addrSpace, dwOffset, data);
  588. }
  589.  
  590. void P9030_ReadWriteBlock (P9030_HANDLE hPlx, DWORD dwLocalAddr, PVOID buf, 
  591.                     DWORD dwBytes, BOOL fIsRead, P9030_ADDR addrSpace, P9030_MODE mode)
  592. {
  593.     DWORD dwOffset = hPlx->addrDesc[addrSpace].dwMask & dwLocalAddr;
  594.     P9030_SetMode (hPlx, addrSpace, mode, dwLocalAddr);
  595.     P9030_ReadWriteSpaceBlock(hPlx, dwOffset, buf, dwBytes, fIsRead, addrSpace, mode);
  596. }
  597.  
  598. void P9030_ReadBlock (P9030_HANDLE hPlx, DWORD dwLocalAddr, PVOID buf, 
  599.                     DWORD dwBytes, P9030_ADDR addrSpace, P9030_MODE mode)
  600. {
  601.     P9030_ReadWriteBlock (hPlx, dwLocalAddr, buf, dwBytes, TRUE, addrSpace, mode);
  602. }
  603.  
  604. void P9030_WriteBlock (P9030_HANDLE hPlx, DWORD dwLocalAddr, PVOID buf, 
  605.                      DWORD dwBytes, P9030_ADDR addrSpace, P9030_MODE mode)
  606. {
  607.     P9030_ReadWriteBlock (hPlx, dwLocalAddr, buf, dwBytes, FALSE, addrSpace, mode);
  608. }
  609.  
  610. BOOL P9030_IntIsEnabled (P9030_HANDLE hPlx)
  611. {
  612.     if (!hPlx->fUseInt) return FALSE;
  613.     if (!hPlx->Int.hThread) return FALSE;
  614.     return TRUE;
  615. }
  616.  
  617. void P9030_IntHandler (PVOID pData)
  618. {
  619.     P9030_HANDLE hPlx = (P9030_HANDLE) pData;
  620.     P9030_INT_RESULT intResult;
  621.     
  622.     intResult.dwCounter = hPlx->Int.Int.dwCounter;
  623.     intResult.dwLost = hPlx->Int.Int.dwLost;
  624.     intResult.fStopped = hPlx->Int.Int.fStopped;
  625.     intResult.dwStatusReg = hPlx->Int.Trans[0].Data.Dword;
  626.     hPlx->Int.funcIntHandler(hPlx, &intResult);
  627. }
  628.  
  629. BOOL P9030_IntEnable (P9030_HANDLE hPlx, P9030_INT_HANDLER funcIntHandler)
  630. {
  631.     DWORD dwIntStatus;
  632.     DWORD dwAddr;
  633.  
  634.     if (!hPlx->fUseInt) return FALSE;
  635.     // check if interrupt is already enabled
  636.     if (hPlx->Int.hThread) return FALSE;
  637.  
  638.     dwIntStatus = P9030_ReadReg (hPlx, P9030_INTCSR);
  639.  
  640.     BZERO(hPlx->Int.Trans);
  641.     // This is a samlpe of handling interrupts:
  642.     // Two transfer commands are issued. First the value of the interrrupt control/status
  643.     // register is read. Then, a value of ZERO is written.
  644.     // This will cancel interrupts after the first interrupt occurs.
  645.     // When using interrupts, this section will have to change:
  646.     // you must put transfer commands to CANCEL the source of the interrupt, otherwise, the 
  647.     // PC will hang when an interrupt occurs!
  648.     dwAddr = hPlx->addrDesc[P9030_ADDR_REG].dwAddr + P9030_INTCSR;
  649.     hPlx->Int.Trans[0].cmdTrans = hPlx->addrDesc[P9030_ADDR_REG].fIsMemory ? RM_DWORD : RP_DWORD;
  650.     hPlx->Int.Trans[0].dwPort = dwAddr;
  651.     hPlx->Int.Trans[1].cmdTrans = hPlx->addrDesc[P9030_ADDR_REG].fIsMemory ? WM_DWORD : WP_DWORD;
  652.     hPlx->Int.Trans[1].dwPort = dwAddr;
  653.     hPlx->Int.Trans[1].Data.Dword = dwIntStatus & ~BIT6; // put here the data to write to the control register
  654.     hPlx->Int.Int.dwCmds = 2; 
  655.     hPlx->Int.Int.Cmd = hPlx->Int.Trans;
  656.     hPlx->Int.Int.dwOptions |= INTERRUPT_CMD_COPY;
  657.  
  658.     // this calls WD_IntEnable() and creates an interrupt handler thread
  659.     hPlx->Int.funcIntHandler = funcIntHandler;
  660.     if (!InterruptThreadEnable(&hPlx->Int.hThread, hPlx->hWD, &hPlx->Int.Int, P9030_IntHandler, (PVOID) hPlx))
  661.         return FALSE;
  662.  
  663.     // this physically enables interrupts
  664.     P9030_WriteReg (hPlx, P9030_INTCSR, dwIntStatus | BIT6);
  665.  
  666.     return TRUE;
  667. }
  668.  
  669. void P9030_IntDisable (P9030_HANDLE hPlx)
  670. {
  671.     DWORD dwIntStatus;
  672.  
  673.     if (!hPlx->fUseInt) return;
  674.     if (!hPlx->Int.hThread) return;
  675.  
  676.     // this disables interrupts
  677.     dwIntStatus = P9030_ReadReg (hPlx, P9030_INTCSR);
  678.     P9030_WriteReg (hPlx, P9030_INTCSR, dwIntStatus & ~BIT6);
  679.  
  680.     // this calls WD_IntDisable()
  681.     InterruptThreadDisable(hPlx->Int.hThread);
  682.  
  683.     hPlx->Int.hThread = NULL;
  684. }
  685.  
  686. void P9030_EEPROMDelay(P9030_HANDLE hPlx)
  687. {
  688.     WD_SLEEP sleep;
  689.     BZERO (sleep);
  690.     sleep.dwMicroSeconds = 500;
  691.     WD_Sleep( hPlx->hWD, &sleep);
  692. }
  693.  
  694. BOOL P9030_EEPROMValid(P9030_HANDLE hPlx)
  695. {
  696.     return (P9030_ReadReg(hPlx, P9030_CNTRL) & BIT28)==BIT28;
  697. }
  698.  
  699. void P9030_Sleep(P9030_HANDLE hPlx, DWORD dwMicroSeconds)
  700. {
  701.     WD_SLEEP sleep;
  702.  
  703.     BZERO (sleep);
  704.     sleep.dwMicroSeconds = dwMicroSeconds;
  705.     WD_Sleep( hPlx->hWD, &sleep);
  706. }
  707.  
  708. BYTE P9030_EEPROMEnable(P9030_HANDLE hPlx, WORD addr)
  709. {
  710.     BYTE old_val;
  711.  
  712.     old_val = P9030_ReadByte(hPlx, P9030_ADDR_REG, P9030_PROT_AREA);
  713.     
  714.     addr /= 4;
  715.     addr &= 0x7f;
  716.  
  717.     P9030_WriteByte(hPlx, P9030_ADDR_REG, P9030_PROT_AREA, (BYTE)addr);
  718.     P9030_Sleep(hPlx, 10000);
  719.  
  720.     return old_val * 4; //expand from dwords to bytes
  721. }
  722.  
  723. void P9030_EEPROMDataReadWrite(P9030_HANDLE hPlx, BOOL fIsRead, PDWORD pdwData)
  724. {
  725.     WD_PCI_CONFIG_DUMP pciCnf;
  726.  
  727.     BZERO (pciCnf);
  728.     pciCnf.pciSlot = hPlx->pciSlot;
  729.     pciCnf.pBuffer = pdwData;
  730.     pciCnf.dwOffset = P9030_VPD_DATA;
  731.     pciCnf.dwBytes = 4;
  732.     pciCnf.fIsRead = fIsRead;
  733.     WD_PciConfigDump(hPlx->hWD,&pciCnf);
  734. }
  735.  
  736. void P9030_EEPROMAddrReadWrite(P9030_HANDLE hPlx, BOOL fIsRead, PWORD pwAddr)
  737. {
  738.     WD_PCI_CONFIG_DUMP pciCnf;
  739.  
  740.     BZERO (pciCnf);
  741.     pciCnf.pciSlot = hPlx->pciSlot;
  742.     pciCnf.pBuffer = pwAddr;
  743.     pciCnf.dwOffset = P9030_VPD_ADDR;
  744.     pciCnf.dwBytes = 2;
  745.     pciCnf.fIsRead = fIsRead;
  746.     WD_PciConfigDump(hPlx->hWD,&pciCnf);
  747. }
  748.  
  749. BOOL P9030_EEPROMReadDWord(P9030_HANDLE hPlx, DWORD dwOffset, PDWORD pdwData)
  750. {
  751.     WORD wVal;
  752.     WORD wAddr;
  753.     int i ;
  754.     BOOL fEnd = FALSE ;
  755.  
  756.     if (dwOffset % 4)
  757.     {
  758.         sprintf (P9030_ErrorString, "The offset is not a multiple of 4\n");
  759.         return FALSE;
  760.     }
  761.     wAddr = (((WORD)dwOffset) & (~BIT15)) ;
  762.  
  763.     
  764.     P9030_EEPROMAddrReadWrite(hPlx, FALSE, &wAddr);
  765.  
  766.     P9030_Sleep(hPlx, 10000);
  767.  
  768.     for (i=0; !fEnd && i<100; i++)
  769.     {
  770.         P9030_EEPROMAddrReadWrite(hPlx, TRUE, &wVal);
  771.         if (wVal & BIT15)
  772.             fEnd = TRUE;
  773.         P9030_Sleep(hPlx, 10000);
  774.     }
  775.     
  776.     if (i==100)
  777.     {
  778.         sprintf (P9030_ErrorString, "Acknoledge to EEPROM read was not recived\n");
  779.         return FALSE;
  780.     }
  781.  
  782.     P9030_EEPROMDataReadWrite(hPlx, TRUE, pdwData);
  783.  
  784.     return TRUE;
  785. }
  786.  
  787. BOOL P9030_EEPROMReadWord(P9030_HANDLE hPlx, DWORD dwOffset, PWORD pwData)
  788. {
  789.     DWORD dwData;
  790.     DWORD dwAddr;
  791.  
  792.     if (dwOffset % 2)
  793.     {
  794.         sprintf (P9030_ErrorString, "The offset is not even\n");
  795.         return FALSE;
  796.     }
  797.     dwAddr = dwOffset - (dwOffset % 4);
  798.  
  799.     if (!P9030_EEPROMReadDWord(hPlx, dwAddr, &dwData))
  800.         return FALSE;
  801.  
  802.     *pwData = (WORD) (dwData >> ((dwOffset % 4)*8));
  803.  
  804.     return TRUE;
  805. }
  806.  
  807. BOOL P9030_EEPROMWriteWord(P9030_HANDLE hPlx, DWORD dwOffset, WORD wData)
  808. {
  809.     DWORD dwData;
  810.     DWORD dwAddr;
  811.  
  812.     dwAddr = dwOffset - (dwOffset % 4);
  813.  
  814.     if (!P9030_EEPROMReadDWord(hPlx, dwAddr, &dwData))
  815.         return FALSE;
  816.  
  817.     switch (dwOffset % 4)
  818.     {
  819.     case 0:
  820.         dwData = (dwData & 0xffff0000) | wData;
  821.         break;
  822.     case 2:
  823.         dwData = (dwData & 0x0000ffff) | (wData << 16);
  824.         break;
  825.     default:
  826.         sprintf (P9030_ErrorString, "The offset is not even\n");
  827.         return FALSE;
  828.     }
  829.  
  830.     return P9030_EEPROMWriteDWord(hPlx, dwAddr, dwData);
  831. }
  832.  
  833. BOOL P9030_EEPROMWriteDWord(P9030_HANDLE hPlx, DWORD dwOffset, DWORD dwData)
  834. {
  835.     DWORD dwReadback;
  836.     WORD wAddr;
  837.     WORD wVal;
  838.     int i;
  839.     BOOL fRet;
  840.     BOOL fEnd = FALSE ;
  841.     BOOL fReadOk = FALSE;
  842.     BYTE bEnableOffset;
  843.  
  844.     if (dwOffset % 4)
  845.     {
  846.         sprintf (P9030_ErrorString, "The offset is not a multiple of 4\n");
  847.         return FALSE;
  848.     }
  849.     wAddr = (WORD)dwOffset;
  850.     bEnableOffset = P9030_EEPROMEnable(hPlx, wAddr);
  851.     wAddr = wAddr | BIT15;
  852.  
  853.     P9030_EEPROMDataReadWrite(hPlx, FALSE, &dwData);
  854.  
  855.     P9030_EEPROMAddrReadWrite(hPlx, FALSE, &wAddr);
  856.  
  857.     P9030_Sleep(hPlx, 10000);
  858.     
  859.     for (i=0; !fEnd && i<100 ;i++)
  860.     {
  861.         P9030_EEPROMAddrReadWrite(hPlx, TRUE, &wVal);
  862.         if ((wVal & BIT15) == 0)
  863.             fEnd = TRUE;
  864.         P9030_Sleep(hPlx, 10000);
  865.     }
  866.  
  867.     fReadOk = P9030_EEPROMReadDWord(hPlx, dwOffset, &dwReadback);
  868.  
  869.     if (fReadOk && dwReadback==dwData)
  870.         fRet = TRUE;
  871.     else
  872.     {
  873.         fRet = FALSE;
  874.         if (fReadOk)
  875.             sprintf (P9030_ErrorString, "Write 0x%08x, Read 0x%08x\n",dwData, dwReadback);
  876.         else
  877.             sprintf (P9030_ErrorString, "Error reading EEPROM\n");
  878.     }
  879.     P9030_EEPROMEnable(hPlx, bEnableOffset); 
  880.     return fRet;
  881. }
  882.